package com.woniuxy.ams.config;

import com.woniuxy.ams.service.AuthService;
import com.woniuxy.ams.shiro.MyRealm;
import com.woniuxy.ams.shiro.filter.ShiroFilter;
import com.woniuxy.ams.shiro.token.JwtToken;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author fyxw
 */
@Configuration
public class ShiroConfig {
    private final RedisTemplate<String,Object> redisTemplate;
    private final AuthService authService;

    /**
     * 使用构造注入
     * @param redisTemplate redisTemplate bean
     * @param authService service bean
     */
    public ShiroConfig(RedisTemplate<String, Object> redisTemplate, AuthService authService) {
        this.redisTemplate = redisTemplate;
        this.authService = authService;
    }

    /**
     * 注入shiro域对象
     * @return shiro域对象bean
     */
    @Bean
    public Realm myRealm() {
        MyRealm myRealm = new MyRealm();
        // 设置自定义的AuthenticationToken实现
        myRealm.setAuthenticationTokenClass(JwtToken.class);
        // 注入redisTemplate
        myRealm.setRedisTemplate(redisTemplate);
        // 注入authService
        myRealm.setAuthService(authService);
        // 设置token需要更新的最小时间
        myRealm.setExpireTimeNeedUpdate(3600);
        return myRealm;
    }

    /**
     * 配置安全管理器
     * @return 安全管理器bean对象
     */
    @Bean
    public DefaultWebSecurityManager mySecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm());
        return securityManager;
    }
    /**
     * 配置我们的过滤器Bean工厂
     */
    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager defaultSecurityManager){
        //1.创建shiro的过滤器工厂
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //2.设置必备属性 安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultSecurityManager);
        //这个key 表示Filter唯一名称，类似web.xml中的filter-name标签
        Map<String, Filter> filters = new HashMap<>(4);
        //3.放入我们自定义的过滤器 并且命名为shiroFilter
        filters.put("shiroFilter",new ShiroFilter());
        //4.再把自定义的Map 一堆过滤器，放入shiro的过滤器工厂中
        shiroFilterFactoryBean.setFilters(filters);
        // 使用linkedHashMap，保证过滤器按照放入得到顺序执行，此处不应该使用HashMap
        // shiro过滤链执行中，如果匹配到某一个url后，不会进入剩余过滤器中
        // 因此必须将需要进行认证的url放到最后
        // 可参考 PathMatchingFilter 中的 preHandle 方法执行过程
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //登录请求 让它匿名访问 无需登录也能进入
        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/**","shiroFilter");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
}
